﻿@page "/recipe/{selectRecipe?}"

@inject IRecipesService RecipeService
@inject IResizeService ResizeService
@implements IDisposable

@if (RecipeService.HasRecipe)
{
    <div class="p-3">
        <div class="fs-3">@RecipeService.RecipeName</div>
        <div>@RecipeService.RecipeDescription</div>
    </div>

    <div class="d-flex">
        <div class="p-2">
            <InputCheckbox class="mx-2 mt-2" @bind-Value=@RecipeService.ShowOpenGL />
            <label>Use OpenGL</label>
        </div>
        <div class="p-2">
            <InputCheckbox class="mx-2 mt-2" @bind-Value=@EnableAutoResizing />
            <label>Resize Plot Automatically</label>
        </div>
    </div>

    @if (RecipeService.ShowOpenGL)
    {
        <BlazorPlotGL @ref=BlazorPlotGL Style="@PlotSize" />
    }
    else
    {
        <BlazorPlot @ref=BlazorPlot Style="@PlotSize" />
    }

    <div class="m-3">
        <div class="bg-light border rounded d-inline-block p-3">
            @if (RecipeService.HasSourceCode)
            {
                <CodeSnippet Code="@RecipeService.SourceCode" />
            }
            else
            {
                <p>Loading...</p>
            }
        </div>
    </div>
}

<div class="text-muted p-4" style="margin-top: 10rem;">
    @ScottPlot.Version.LongString Running on .NET @Environment.Version
</div>

@code {
    [Parameter]
    public string SelectRecipe { get; set; } = string.Empty;

    BlazorPlot BlazorPlot { get; set; } = new();
    BlazorPlotGL BlazorPlotGL { get; set; } = new();
    string SearchTerm { get; set; } = "";

    const string DefaultPlotSize = "width: min(100%, 800px); height: 600px;";
    string PlotSize { get; set; } = DefaultPlotSize;

    protected override void OnInitialized()
    {
        RecipeService.RecipeChanged += this.RefreshWithPlot;
        RecipeService.BackendChanged += this.RefreshWithPlot;

        ResizeService.Enable = false;
        ResizeService.ResizeAction += this.ResizePlot;
    }

    public void Dispose()
    {
        RecipeService.RecipeChanged -= this.RefreshWithPlot;
        RecipeService.BackendChanged -= this.RefreshWithPlot;
        ResizeService.ResizeAction -= this.ResizePlot;
    }

    protected override void OnParametersSet()
    {
        ReloadSelectedRecipe();
    }

    private void ReloadSelectedRecipe()
    {
        if (string.IsNullOrEmpty(SelectRecipe))
            return;

        if (RecipeService.FindRecipe(SelectRecipe))
        {
            ShowRecipe(RecipeService.Recipe!);
        }
    }

    protected void RefreshWithPlot()
    {
        StateHasChanged();
        UpdatePlot();
    }

    protected void UpdatePlot()
    {
        InvokeAsync(async () =>
        {
            await Task.Delay(1);
            IPlotControl plotControl = RecipeService.ShowOpenGL ? BlazorPlotGL : BlazorPlot;
            plotControl.Reset();
            RecipeService.Recipe?.Execute(plotControl.Plot);
            plotControl.Plot.RenderInMemory();
            plotControl.Refresh();
        });
    }

    protected void ShowRecipe(IRecipe recipe)
    {
        RecipeService.Recipe = recipe;
        UpdatePlot();
    }

    private bool EnableAutoResizing
    {
        get => ResizeService.Enable;
        set
        {
            ResizeService.Enable = value;
            PlotSize = DefaultPlotSize;
        }
    }

    /// <summary>
    /// The Layout's OnAfterRenderAsync() method calls UpdateDisplayField()
    /// which calls the ResizeService's SetSize() method and if the size
    /// has changed it invokes this action.
    /// </summary>
    protected void ResizePlot(System.Drawing.SizeF newSize)
    {
        double width = newSize.Width;
        double height = Math.Max(newSize.Height * 0.5, 240);
        PlotSize = $"width: min(100%, {width:F0}px); height: {height:F0}px;";
        RefreshWithPlot();
    }
}

